<script setup lang='ts'>
import type { FormItemRule } from 'element-plus'
import type { PlusColumn } from 'plus-pro-components'

import { useAddMenu, useEditMenu, useGetMenuInfo } from '@fl/api/man-api'
import { SubmitBtn } from '@fl/components'
import { cloneDeep } from 'lodash-es'

const menuId = defineModel<string>('menuId', { required: true })
const type = defineModel<string>('type', { required: true })
const menuList = defineModel<any>('menuList', { required: true })
const visible = defineModel<boolean>('visible', { required: true })
const formRef = ref()
const title = computed(() => {
    return type.value ? '编辑菜单' : '新增菜单'
})

type Istate = {
    activeMenu?: string
    component?: string
    icon?: string
    isCache?: string
    isFrame?: string
    menuId?: number | string
    menuName?: string
    menuType?: string
    orderNum?: number
    parentId?: number | string
    path?: string
    perms?: string
    query?: string
    status?: string
    visible?: string
}

const initialState = {
    activeMenu: '',
    component: '',
    icon: '',
    isCache: '0',
    isFrame: '1',
    menuId: '',
    menuName: '',
    menuType: 'M',
    orderNum: 0,
    parentId: '',
    path: '',
    perms: '',
    query: '',
    status: '0',
    visible: '0',
}
const state = ref<Istate>(cloneDeep(initialState))
const currentMenuId = ref<string>('')

const columns: PlusColumn[] = [
    {
        label: '上级菜单',
        prop: 'menuId',
    },
    {
        label: '菜单类型',
        options: [
            {
                label: '目录',
                value: 'M',
            },
            {
                label: '菜单',
                value: 'C',
            },
            {
                label: '按钮',
                value: 'F',
            },
        ],
        prop: 'menuType',
        valueType: 'radio',
    },
    {
        // fieldProps: disabledFieldProps,
        hideInForm: computed(() => state.value.menuType === 'F'),
        label: '菜单图标',
        prop: 'icon',
    },
    {
        // fieldProps: disabledFieldProps,
        label: '菜单名称',
        prop: 'menuName',
    },
    {
        fieldProps: { min: 0 },
        label: '显示排序',
        prop: 'orderNum',
        valueType: 'input-number',
    },
    {
        hideInForm: computed(() => state.value.menuType === 'F'),
        label: '路由地址',
        prop: 'path',
    },
    {
        hideInForm: computed(() => state.value.menuType === 'M' || state.value.menuType === 'F'),
        label: '组件路径',
        prop: 'component',
    },
    {
        hideInForm: computed(() => state.value.menuType === 'M' || state.value.menuType === 'F'),
        label: '高亮路由',
        prop: 'activeMenu',
    },
    { hideInForm: computed(() => state.value.menuType === 'M'), label: '权限字符', prop: 'perms' },
    {
        hideInForm: computed(() => state.value.menuType === 'M' || state.value.menuType === 'F'),
        label: '路由参数',
        prop: 'query',
    },
    {
        colProps: {
            span: 12,
        },
        hideInForm: computed(() => state.value.menuType === 'F'),
        label: '是否外链',
        options: [
            {
                label: '是',
                value: '0',
            },
            {
                label: '否',
                value: '1',
            },
        ],
        prop: 'isFrame',
        valueType: 'radio',
    },
    {
        colProps: {
            span: 12,
        },
        hideInForm: computed(() => state.value.menuType === 'M' || state.value.menuType === 'F'),
        label: '是否缓存',
        options: [
            {
                label: '缓存',
                value: '0',
            },
            {
                label: '不缓存',
                value: '1',
            },
        ],
        prop: 'isCache',
        valueType: 'radio',
    },
    {
        colProps: {
            span: 12,
        },
        hideInForm: computed(() => state.value.menuType === 'F'),
        label: '显示状态',
        options: [
            {
                label: '显示',
                value: '0',
            },
            {
                label: '隐藏',
                value: '1',
            },
        ],
        prop: 'visible',
        valueType: 'radio',
    },
    {
        colProps: {
            span: 12,
        },
        label: '菜单状态',
        options: [
            {
                label: '正常',
                value: '0',
            },
            {
                label: '停用',
                value: '1',
            },
        ],
        prop: 'status',
        valueType: 'radio',
    },
]

function validateMenuName(_rule: FormItemRule, value: string, callback: Fn): void {
    const pattern = /\s/
    if (!value) {
        callback(new Error('请输入菜单名称'))
    }
    if (pattern.test(value))
        callback(new Error('菜单名称不允许输入空格'))

    else
        callback()
}

const rules = {
    menuId: [
        {
            message: '请选择上级菜单',
            required: true,
            trigger: 'blur',
        },
    ],
    menuName: [
        {
            required: true,
            trigger: ['blur', 'change'],
            validator: validateMenuName,
        },
    ],
    orderNum: [
        {
            message: '请输入排序',
            required: true,
            trigger: 'blur',
        },
    ],
    path: [
        {
            message: '请输入路由地址',
            required: true,
            trigger: 'blur',
        },
    ],
}

const { isPending: addMenuPending, mutate } = useAddMenu()
const { isPending: editMenuPending, mutate: editMenuMutate } = useEditMenu()
const { data: menuInfo, isLoading: menuInfoLoading } = useGetMenuInfo(menuId)

const isLoading = computed(() => {
    return menuInfoLoading.value
})
const isPending = computed(() => {
    return addMenuPending.value || editMenuPending.value
})

const cascaderProps = { checkStrictly: true, emitPath: false, label: 'menuName', value: 'menuId' }
const cascaderOpitons = computed(() => {
    return menuList.value ? toRaw(menuList.value) : []
})

watchEffect(() => {
    if (menuId.value) {
        if (menuInfo.value) {
            state.value = {
                activeMenu: menuInfo.value.activeMenu || '',
                component: menuInfo.value.component || '',
                icon: menuInfo.value.icon || '',
                isCache: menuInfo.value.isCache,
                isFrame: menuInfo.value.isFrame,
                menuId: menuInfo.value.parentId,
                menuName: menuInfo.value.menuName,
                menuType: menuInfo.value.menuType,
                orderNum: menuInfo.value.orderNum,
                parentId: menuInfo.value.parentId,
                path: menuInfo.value.path || '',
                perms: menuInfo.value.perms || '',
                query: menuInfo.value.query || '',
                status: menuInfo.value.status,
                visible: menuInfo.value.visible,
            }
            currentMenuId.value = menuInfo.value.menuId
            console.log(state.value, 'state.value')
        }
    }
})

function findNodeById(nodes, nodeId) {
    for (const node of nodes) {
        if (node.menuId === nodeId) {
            return node
        }

        if (node.children) {
            const foundNode = findNodeById(node.children, nodeId)
            if (foundNode) {
                return foundNode
            }
        }
    }

    return null
}

function handleChange(value) {
    const obj = findNodeById(cascaderOpitons.value, value)
    console.log(obj, 'obj')
    state.value.parentId = obj.menuId
}

function cancel() {
    visible.value = false
}

async function confirm() {
    const valid = await formRef.value.formInstance.validate()
    if (valid) {
        console.log(state.value, 'state.value')
        const params = {
            ...state.value,
            menuId: currentMenuId.value ? currentMenuId.value : state.value.menuId,
        }
        if (type.value === 'add') {
            params.menuId = ''
        }
        else {
            params.menuId = currentMenuId.value
        }
        console.log(params, 'params')
        const fn = menuId.value ? editMenuMutate : mutate

        fn(params, {
            onSuccess: () => {
                ElMessage.success('操作成功')
                cancel()
            },
        })
    }
}

function reset() {
    menuId.value = ''
    formRef.value.formInstance.resetFields()
}
</script>

<template>
    <PlusDialog v-model="visible"
                :title="title"
                width="600"
                close-on-press-escape
                @cancel="cancel"
                @closed="reset"
    >
        <ElSkeleton v-if="isLoading"
                    animated
        />

        <PlusForm v-else
                  ref="formRef"
                  v-model="state"
                  :columns="columns"
                  :label-width="100"
                  :rules="rules"
                  :has-footer="false"
        >
            <template #plus-field-menuId>
                <el-cascader v-model="state.menuId"
                             :options="cascaderOpitons"
                             :props="cascaderProps"
                             clearable
                             filterable
                             :show-all-levels="false"
                             class="w-full"
                             placeholder="请选择上级菜单"
                             @change="handleChange"
                />
            </template>
        </PlusForm>

        <template #footer>
            <div class="mx-auto">
                <el-button @click="cancel">
                    取消
                </el-button>

                <SubmitBtn type="primary"
                           :loading="isPending"
                           @click="confirm"
                >
                    提交
                </SubmitBtn>
            </div>
        </template>
    </PlusDialog>
</template>

<style scoped lang='less'>
</style>
